package com.zzyl.nursing.service.impl;

import cn.hutool.core.bean.BeanException;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.zzyl.common.constant.CacheConstants;
import com.zzyl.common.core.domain.entity.SysUser;
import com.zzyl.common.userThreadLocal.UserThreadLocal;
import com.zzyl.common.utils.SecurityUtils;
import com.zzyl.nursing.domain.CheckIn;
import com.zzyl.nursing.domain.CheckInConfig;
import com.zzyl.nursing.domain.Elder;
import com.zzyl.nursing.domain.NursingTask;
import com.zzyl.nursing.dto.NursingTaskCancelDto;
import com.zzyl.nursing.dto.NursingTaskExecuteDto;
import com.zzyl.nursing.dto.NursingTaskExecuteResultDto;
import com.zzyl.nursing.mapper.*;
import com.zzyl.nursing.service.INursingTaskService;
import com.zzyl.nursing.vo.NursingTaskDetailVo;
import com.zzyl.nursing.vo.NursingTaskVo;
import com.zzyl.serve.domain.*;
import com.zzyl.serve.mapper.*;
import com.zzyl.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;


/**
 * 护理任务Service业务层处理
 *
 * @author ruoyi
 * @date 2025-08-04
 */
@Service
public class NursingTaskServiceImpl extends ServiceImpl<NursingTaskMapper, NursingTask> implements INursingTaskService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private NursingElderMapper nursingElderMapper;
    //调用系统角色的mapper层
    @Autowired
    private SysUserMapper sysUserMappers;
    //调用项目计划项目的mapper层
    @Autowired
    private NursingProjectPlanMapper nursingProjectPlanMapper;
    //调用护理等级的mapper层
    @Autowired
    private NursingLevelMapper nursingLevelMapper;
    //调用老人的mapper层
    @Autowired
    private ElderMapper elderMapper;
    //护理计划表
    @Autowired
    private NursingPlanMapper nursingPlanMapper;
    @Autowired
    private NursingProjectMapper nursingProjectMapper;
    @Autowired
    private CheckInMapper checkInMapper;
    @Autowired
    private ElderServiceImpl elderService;
    @Autowired
    private CheckInConfigMapper checkInConfigMapper;
    @Autowired
    private NursingTaskMapper nursingTaskMapper;
    @Autowired
    private com.zzyl.nursing.task.NursingTask nursingTask;

    /**
     * 查询护理任务详情
     *
     * @param id 护理任务主键
     * @return 护理任务
     */
    @Override
    public NursingTaskDetailVo selectNursingTaskById(Integer id) {
        //从数据库中读取数据
        NursingTask nursingTask = getById(id);
        //属性copy
        NursingTaskDetailVo nursingTaskDetailVo = new NursingTaskDetailVo();
        BeanUtil.copyProperties(nursingTask, nursingTaskDetailVo);
        //如果当前为已经执行，需获取执行人姓名
        if (nursingTaskDetailVo.getStatus()==2){
//            nursingTaskDetailVo.setNursingName();
        }
        List<String> nursingName=new ArrayList<>();
        //获取护理人员的姓名
        String[] strings = nursingTask.getNursingId().split(",");
        for (int i = 0; i < strings.length; i++) {
            SysUser sysUser = sysUserMappers.selectUserById(Long.valueOf(strings[i]));
            String nickName = sysUser.getNickName();
            nursingName.add(nickName);
        }
        nursingTaskDetailVo.setNursingName(nursingName);
        CheckIn checkIn = checkInMapper.selectOne(Wrappers.<CheckIn>lambdaQuery().eq(CheckIn::getElderId, nursingTask.getElderId()));
        nursingTaskDetailVo.setNursingLevelName(checkIn.getNursingLevelName());
        Elder elder = elderMapper.selectById(nursingTask.getElderId());
        String birthday = elder.getBirthday();
        System.out.println(birthday);
        int i = calculateAge(birthday);
        nursingTaskDetailVo.setAge(i);
        //设置执行人姓名
        SysUser sysUser = sysUserMappers.selectUserById(Long.valueOf(nursingTask.getUpdateBy()));
        nursingTaskDetailVo.setUpdater(sysUser.getNickName());
        //设置性别
        Integer sex = elder.getSex();
        if (sex==0) {
            nursingTaskDetailVo.setSex("女");
        }else{
            nursingTaskDetailVo.setSex("男");
        }
        return nursingTaskDetailVo;
    }
    /**
     * 根据出生日期字符串计算年龄
     *
     * @param birthDateString 出生日期字符串 (格式: yyyy-MM-dd)
     * @return 年龄
     */
    public int calculateAge(String birthDateString) {
        if (birthDateString == null || birthDateString.isEmpty()) {
            return 0;
        }
        try {
            LocalDate birthDate = LocalDate.parse(birthDateString);
            LocalDate currentDate = LocalDate.now();
            // 如果出生日期是未来日期，返回0
            if (birthDate.isAfter(currentDate)) {
                return 0;
            }
            return java.time.Period.between(birthDate, currentDate).getYears();
        } catch (Exception e) {
            // 日期格式不正确时返回0
            return 0;
        }
    }

    /**
     * 查询护理任务列表
     *
     * @param nursingTask 护理任务
     * @param pageNum 页码
     * @param pageSize 每页数量
     * @return 护理任务分页结果
     */
    /**
     * 查询护理任务列表
     *
     * @param nursingTask 护理任务
     * @param pageNum 页码
     * @param pageSize 每页数量
     * @return 护理任务分页结果
     */
    @Override
    @Transactional
    public IPage<NursingTaskVo> selectNursingTaskList(NursingTask nursingTask, Integer pageNum, Integer pageSize) {
        // 创建 MyBatis-Plus 分页对象
        IPage<NursingTask> page = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(pageNum, pageSize);

        // 构建查询条件
        LambdaQueryWrapper<NursingTask> queryWrapper = new LambdaQueryWrapper<>();

        // 状态条件
        if (nursingTask.getStatus() != null) {
            queryWrapper.eq(NursingTask::getStatus, nursingTask.getStatus());
        }

        // 老人姓名模糊查询
        if (nursingTask.getElderName() != null && !nursingTask.getElderName().isEmpty()) {
            queryWrapper.like(NursingTask::getElderName, nursingTask.getElderName());
        }

        // 护理员ID查询
        if (nursingTask.getNursingId() != null && !nursingTask.getNursingId().isEmpty()) {
            // 使用自定义SQL片段处理包含指定护理员ID的查询
            queryWrapper.apply("FIND_IN_SET({0}, nursing_id)", nursingTask.getNursingId());
        }

        // 执行分页查询
        IPage<NursingTask> nursingTaskPage = this.page(page, queryWrapper);

        // 转换为Vo对象
        List<NursingTaskVo> voList = new ArrayList<>();
        if (!CollUtil.isEmpty(nursingTaskPage.getRecords())) {
            nursingTaskPage.getRecords().forEach(temp -> {
                // 将符合返回类型的属性进行copy
                NursingTaskVo nursingTaskVo = BeanUtil.toBean(temp, NursingTaskVo.class);

                // 调用老人护理的mapper层方法，获取NursingElder列表，以此来获取护理人员id
                List<NursingElder> nursingElders = nursingElderMapper.selectList(Wrappers.<NursingElder>lambdaQuery().eq(NursingElder::getElderId, temp.getElderId()));
                if (!CollUtil.isEmpty(nursingElders)) {
                    // 获取护理人员姓名
                    List<String> nursingName = new ArrayList<>();
                    nursingElders.forEach(tempNursing -> {
                        SysUser sysUser = sysUserMappers.selectUserById(tempNursing.getNursingId());
                        if (sysUser != null && sysUser.getNickName() != null) {
                            nursingName.add(sysUser.getNickName());
                        }
                    });
                    nursingTaskVo.setNursingName(nursingName);
                }

                voList.add(nursingTaskVo);
            });
        }

        // 构建返回的分页对象
        IPage<NursingTaskVo> resultPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(pageNum, pageSize, nursingTaskPage.getTotal());
        ((com.baomidou.mybatisplus.extension.plugins.pagination.Page<NursingTaskVo>) resultPage).setRecords(voList);

        // 更新缓存
        redisTemplate.opsForValue().set(CacheConstants.NURSING_TASK, JSONUtil.toJsonStr(nursingTaskPage.getRecords()));

        return resultPage;
    }


    /**
     * 自动生成护理任务
     */
    //只使用单表进行查询
    @Override
    public void createNursingTask() {
        //通过入住表获取老人信息,必须是已经入住
        List<CheckIn> checkIns = checkInMapper.selectList(Wrappers.<CheckIn>lambdaQuery().eq(CheckIn::getStatus, 0));
        if (CollUtil.isEmpty(checkIns)) {
            throw new BeanException("没有入住信息，无法生成护理任务");
        }
        checkIns.forEach(checkin -> {
            //判断当前时间是否在费用期限中
            CheckInConfig checkInConfig = checkInConfigMapper.selectOne(Wrappers.<CheckInConfig>lambdaQuery().eq(CheckInConfig::getCheckInId, checkin.getId()));
            LocalDate feeStartDate = checkInConfig.getFeeStartDate().toLocalDate();
            LocalDate feeEndDate = checkInConfig.getFeeEndDate().toLocalDate();
            LocalDate nowTime = LocalDate.now();
            // 检查当前时间是否在费用期限内
            if (nowTime.isAfter(feeStartDate) && nowTime.isBefore(feeEndDate)) {
                // 当前日期在费用期限内，可以执行相关操作
                System.out.println("在费用期限内");
            } else {
                // 当前日期不在费用期限内
                return;
            }
            //根据老人身份证号获取老人信息
            Elder elder = elderService.getOne(Wrappers.<Elder>lambdaQuery().eq(Elder::getIdCardNo, checkin.getIdCardNo()));
            List<NursingTask> nursingTaskList = new ArrayList<>();

            //调用老人护理的mapper层方法，获取NursingElder列表，以此来获取护理人员id
            List<NursingElder> nursingElders = nursingElderMapper.selectList(Wrappers.<NursingElder>lambdaQuery().eq(NursingElder::getElderId, elder.getId()));

            if (CollUtil.isEmpty(nursingElders)) {
                throw new BeanException("没有老人和护理中间表的信息，无法生成护理任务");
            }

            //进行护理老人中间表的遍历遍历，获取护理人员姓名，并装入到String类型的集合中
            List<String> nursingIdList = new ArrayList<>();
            nursingElders.forEach(tempNursing -> {
                nursingIdList.add(tempNursing.getNursingId().toString());
            });

            //根据护理等级的名称(护理等级名称唯一)获取护理等级信息表
            NursingLevel nursingLevel = nursingLevelMapper.selectOne(Wrappers.<NursingLevel>lambdaQuery().eq(NursingLevel::getName, checkin.getNursingLevelName()));

            if (nursingLevel == null) {
                throw new BeanException("没有确切的护理等级信息，无法生成护理任务");
            }

            //根据护理等级获取护理计划，ps:一个护理等级只能有一个护理计划
            NursingPlan nursingPlan = nursingPlanMapper.selectOne(Wrappers.<NursingPlan>lambdaQuery().eq(NursingPlan::getId, nursingLevel.getPlanId()));

            // 增加空值检查
            if (nursingPlan == null) {
                throw new BeanException("没有护理计划信息，无法生成护理任务");
            }

            //根据护理计划获取多个护理项目,并开始封装任务信息
            List<NursingProjectPlan> list = nursingProjectPlanMapper.selectList(Wrappers.<NursingProjectPlan>lambdaQuery().eq(NursingProjectPlan::getPlanId, nursingPlan.getId()));

            // 增加空值检查
            if (CollUtil.isEmpty(list)) {
                throw new BeanException("查询不到护理计划和项目的中间表信息，无法生成护理任务");
            }

            list.forEach(temp -> {
                //查询护理项目，且护理项目为启用状态
                NursingProject nursingProject = nursingProjectMapper.selectOne(Wrappers.<NursingProject>lambdaQuery().eq(NursingProject::getId, temp.getProjectId()).eq(NursingProject::getStatus, 1));
                // 增加空值检查
                if (nursingProject == null) {
                    throw new BeanException("没有护理项目信息，无法生成护理任务");
                }

                NursingTask nursingTask1 = new NursingTask();
                nursingTask1.setProjectId(Integer.valueOf(nursingProject.getId().toString()));
                nursingTask1.setProjectName(nursingProject.getName());
                nursingTask1.setElderId(Integer.valueOf(elder.getId().toString()));
                nursingTask1.setElderName(elder.getName());
                nursingTask1.setBedNumber(elder.getBedNumber());
                nursingTask1.setNursingId(String.join(",", nursingIdList));
                nursingTask1.setStatus(1); // 设置为待执行状态
                //根据不同的护理计划施行时间，设置不同的预期执行时间
                String executeTime = temp.getExecuteTime();
                if (executeTime != null && !executeTime.isEmpty()) {
                    String dateTimeStr = LocalDate.now().toString() + " " + executeTime;
                    // 使用指定的日期时间格式进行解析
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    nursingTask1.setEstimatedServerTime(LocalDateTime.parse(dateTimeStr, formatter));
                } else {
                    // 如果没有执行时间，默认设置为当前时间
                    nursingTask1.setEstimatedServerTime(LocalDateTime.now());
                }
                nursingTaskList.add(nursingTask1);
            });
            // 批量保存护理任务
            if (!nursingTaskList.isEmpty()) {
                //判断数据库是否已有数据
                List<NursingTask> list1 = list();
                saveBatch(nursingTaskList);
                list1.addAll(nursingTaskList);
                redisTemplate.opsForValue().set(CacheConstants.NURSING_TASK, JSONUtil.toJsonStr(list1));
            }
        });
    }

    /**
     * 取消任务
     *
     * @param nursingTaskCancelDto
     */
    @Transactional
    @Override
    public void cacelTask(NursingTaskCancelDto nursingTaskCancelDto) {
        //清除redis中的数据
        redisTemplate.delete(CacheConstants.NURSING_TASK);
        System.out.println();
        //根据任务id更新数据
        update(Wrappers.<NursingTask>lambdaUpdate().eq(NursingTask::getId, nursingTaskCancelDto.getTaskId())
                .set(NursingTask::getStatus, 3)
                .set(NursingTask::getUpdateBy, SecurityUtils.getUserId())
                .set(NursingTask::getCancelReason, nursingTaskCancelDto.getReason())
                .set(NursingTask::getUpdateTime,LocalDateTime.now()));
    }

    /**
     * 执行任务
     *
     * @param nursingTaskExecuteDto
     */
    @Transactional
    @Override
    public void executeTask(NursingTaskExecuteDto nursingTaskExecuteDto) {
        //先删除redis中的文件
        redisTemplate.delete(CacheConstants.NURSING_TASK);
        //根据数据更新
        update(Wrappers.<NursingTask>lambdaUpdate().eq(NursingTask::getId, nursingTaskExecuteDto.getTaskId())
                .set(NursingTask::getTaskImage, nursingTaskExecuteDto.getTaskImage())
                .set(NursingTask::getEstimatedServerTime, nursingTaskExecuteDto.getEstimatedServerTime())
                .set(NursingTask::getMark, nursingTaskExecuteDto.getMark())
                .set(NursingTask::getRealServerTime,LocalDateTime.now())
                .set(NursingTask::getUpdateBy, SecurityUtils.getUserId())
                .set(NursingTask::getUpdateTime,LocalDateTime.now())
                .set(NursingTask::getStatus, 2));
        System.out.println(SecurityUtils.getUserId());
    }

    /**
     * 任务改期
     *
     * @param nursingTaskExecuteResultDto
     */
    @Override
    public void updateTask(NursingTaskExecuteResultDto nursingTaskExecuteResultDto) {
        //先删除redis中的文件
        redisTemplate.delete(CacheConstants.NURSING_TASK);
        //根据数据更新
        update(Wrappers.<NursingTask>lambdaUpdate().eq(NursingTask::getId, nursingTaskExecuteResultDto.getTaskId())
                .set(NursingTask::getEstimatedServerTime, LocalDateTime.parse(nursingTaskExecuteResultDto.getEstimatedServerTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
                .set(NursingTask::getUpdateBy, SecurityUtils.getUserId())
                .set(NursingTask::getUpdateTime,LocalDateTime.now())
                .set(NursingTask::getStatus, 1));

    }
}

